from PyQt4 import QtCore, QtNetwork
import bz2

class SocketBase(QtCore.QObject):
        
        modeNone = -1
        modeServer = 0
        modeClient = 1
        
        def __init__(self, parent=None):
            QtCore.QObject.__init__(self, parent)
            self.socket = QtNetwork.QTcpSocket()
            self.connect(self.socket,QtCore.SIGNAL("connected()"), self.socketConnected)
            self.mode = SocketBase.modeNone
            
            self.pkg = "" #data
            self.remaining = 0
            self.size = 0
            
        def setSocketSignals(self,bool):
            if bool:
                self.setSocketSignals(False)
                self.connect(self.socket,QtCore.SIGNAL("stateChanged(QAbstractSocket::SocketState)"), self.socketStateChange)
                self.connect(self.socket,QtCore.SIGNAL("readyRead()"), self.socketNewData)
            else:
                self.disconnect(self.socket,QtCore.SIGNAL("stateChanged(QAbstractSocket::SocketState)"), self.socketStateChange)
                self.disconnect(self.socket,QtCore.SIGNAL("readyRead()"), self.socketNewData)
            
        def socketStateChange(self,state):
            self.log(QtCore.QCoreApplication.translate("SocketBase","Socket State Changed to %1").arg(state))
            if state == 0:
                self.socketDisconnected()
            
        def socketConnected(self):
            self.log(QtCore.QCoreApplication.translate("SocketBase","Socket Connected"))
            #self.setSocketSignals(True)
            self.emit(QtCore.SIGNAL("socketConnected()"))
        
        def socketDisconnected(self):
            self.log(QtCore.QCoreApplication.translate("SocketBase","Socket Disconnected"))
            self.setSocketSignals(False)
            self.emit(QtCore.SIGNAL("socketDisconnected()"))
            
        def socketNewData(self):
            
            #print "remaining-start", self.remaining
            if self.remaining == 0:
                #print "rem 0"
                self.size = int(self.socket.read(12))
                #print "supposed size:", self.size
                self.remaining = self.size - self.socket.bytesAvailable()
                
                #print "remaining-2", self.remaining
                if self.remaining ==  0:
                    #print "rem2  0"
                    data = self.socket.read(self.size)
                    data = bz2.decompress(data)
                    self.emit(QtCore.SIGNAL("socketNewData(QByteArray)"),data)
                else:
                    if self.remaining > 0:
                        #print "rem +0"
                        self.pkg = self.pkg + self.socket.readAll()
                    elif self.remaining < 0:
                        #print "rem -0"
                        data = self.socket.read(self.size)
                        data = bz2.decompress(data)
                        self.emit(QtCore.SIGNAL("socketNewData(QByteArray)"),data)
                        self.remaining = 0
                        
                        self.socketNewData()
            else:
                if self.socket.bytesAvailable() > self.remaining:

                    self.pkg = self.pkg + self.socket.read(self.remaining)
                    self.pkg = bz2.decompress(self.pkg)
                    self.emit(QtCore.SIGNAL("socketNewData(QByteArray)"),self.pkg)
                    self.pkg = ""
                    self.remaining = 0
                elif self.socket.bytesAvailable() == self.remaining:
                    
                    self.remaining = self.remaining - self.socket.bytesAvailable()
                    self.pkg = self.pkg + self.socket.readAll()
                    self.pkg = bz2.decompress(self.pkg)
                    self.emit(QtCore.SIGNAL("socketNewData(QByteArray)"),self.pkg)
                    self.pkg = ""
                else:
                    
                    self.remaining = self.remaining - self.socket.bytesAvailable()
                    self.pkg = self.pkg + self.socket.readAll()
            
        def socketSendData(self,data):
            data = bz2.compress(data)
            size = str(len(data))
            while(len(size)<12):
                size = "0" + size
            data = size + data
            self.socket.write(data)
            self.socket.flush()
            
        def disconnectSocket(self):
            self.socket.flush()
            self.socket.disconnectFromHost()
            
        def log(self,msg):
            self.emit(QtCore.SIGNAL("log(QString)"),"SocketBase:: " + msg)
            
        def getRemoteInfo(self):
            info = self.socket.peerName() + ":" + str(self.socket.peerPort())
            return info

class Server(SocketBase):
        def __init__(self, parent=None):
            SocketBase.__init__(self)
            
            self.socketServer = QtNetwork.QTcpServer()
            self.mode = SocketBase.modeServer
            self.port = 4000
            
        def start(self):
            self.connect(self.socketServer, QtCore.SIGNAL("newConnection()"), self.newConnection)
            if self.socketServer.listen(QtNetwork.QHostAddress("0.0.0.0"),self.port):
                self.log(QtCore.QCoreApplication.translate("SocketBase","Server Started at Port %1").arg(self.port))
                self.emit(QtCore.SIGNAL("socketConnecting()"))
            else:
                self.log(QtCore.QCoreApplication.translate("SocketBase","Can't listen to %1").arg(self.port))
            
        def newConnection(self):
            socket = self.socketServer.nextPendingConnection()
            if self.socket.state() == QtNetwork.QTcpSocket.UnconnectedState:
                self.socket = socket
                self.setSocketSignals(True)
                self.log(QtCore.QCoreApplication.translate("SocketBase","Accepted Connection"))
                self.socketConnected()
            else:
                socket.disconnectFromHost()
                self.log(QtCore.QCoreApplication.translate("SocketBase","Rejected Connection"))
        
        def stop(self):
            self.socket.disconnectFromHost()
            self.socketServer.close()
            self.socketDisconnected()
            self.log(QtCore.QCoreApplication.translate("SocketBase","Server Stopped"))

class Client(SocketBase):
        def __init__(self, parent=None):
            SocketBase.__init__(self)
            
            self.mode = SocketBase.modeClient
            self.port = 4000
            self.ip = "127.0.0.1"
            
        def start(self):
            self.setSocketSignals(True)
            self.socket.connectToHost(self.ip,self.port)
            self.log(QtCore.QCoreApplication.translate("SocketBase","Connecting..."))
            self.emit(QtCore.SIGNAL("socketConnecting()"))
